using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Globalization;
using System.Linq;
using HomeDMSObjectModel;
using NHibernate;
using System.IO;

namespace HomeDms
{
    public partial class DocumentForm : Form
    {
        private DBHelper _dbHelper;
        private ISession _session;
        private Document _doc;

        internal DBHelper DBHelperProp
        {
            set { _dbHelper = value; }
        }
	
        public DocumentForm()
        {
            InitializeComponent();
        }

        public Document Document
        {
            get
            {
                return _doc;
            }

            set
            {
                _doc = value;
            }
        }

        private void AcquireButton_Click(object sender, EventArgs e)
        {
            ScanForm sf = new ScanForm();
            if (sf.ShowDialog() == DialogResult.OK)
                AddPage(sf.ScannedImage);
            sf.Dispose();
        }

        private void AddPage(Image image,string name)
        {
            string pageName;
            if (string.IsNullOrEmpty(name))
            {
                pageName = "Page " + (pagesFlowLayoutPanel.Controls.Count + 1).ToString();
            }
            else
            {
                pageName = name;
            }                 
            PageControl page = new PageControl(pageName, image);
            pagesFlowLayoutPanel.Controls.Add(page);
        }

        private void AddPage(Image image)
        {
            AddPage(image, null);
        }

        public event EventHandler DocumentsUpdated;

        private void NewDocumentForm_Load(object sender, EventArgs e)
        {
            FillDefaultValues();
            if (_doc != null)
                FillDocumentValues();
            UpdateControls();            
        }

        private void FillDocumentValues()
        {
            // attach _doc to _session
            _session.Update(_doc);
            NameTextBox.Text = _doc.Name;
            txtDescription.Text = _doc.Description;
            DocTagListBox.Items.AddRange(_doc.Tags.ToArray<Tag>());
            foreach (Page page in _doc.Pages)
            {
                PageControl pageCtl = new PageControl(page);
                pagesFlowLayoutPanel.Controls.Add(pageCtl);
            }
        }
        
        List<Tag> allTagList = new List<Tag>();

        private void FillDefaultValues()
        {
            var q = from cult in CultureInfo.GetCultures(CultureTypes.AllCultures)
                    orderby cult.DisplayName
                    select cult;
            comboBox1.Items.Clear();
            comboBox1.Items.AddRange(q.ToArray<CultureInfo>());
            DocTagListBox.Items.Clear();
            _session = _dbHelper.OpenSession();
            ICriteria allTags = _session.CreateCriteria(typeof(Tag));
            allTagList.Clear();
            allTagList.AddRange(allTags.List<Tag>());
            AllTagListBox.Items.Clear();
            AllTagListBox.Items.AddRange(allTags.List<Tag>().ToArray<Tag>());
            List<string> l = _session.CreateQuery("select doc.Name from Document doc").List<string>() as List<string>;
            AutoCompleteStringCollection autoc = new AutoCompleteStringCollection();
            autoc.AddRange(l.ToArray());
            NameTextBox.AutoCompleteCustomSource = autoc;
            NameTextBox.Focus();
        }

        private void AddTagButton_Click(object sender, EventArgs e)
        {
            //AddNewTagForm dialog = new AddNewTagForm();
            //DialogResult res = dialog.ShowDialog(this);
            //if (res == DialogResult.OK)
            //{
                using (ITransaction trans = _session.BeginTransaction())
                {
                    try
                    {
                        Tag tag = new Tag();
                        tag.Name = textBox2.Text;
                        _session.Save(tag);
                        trans.Commit();
                        allTagList.Add(tag);
                        DocTagListBox.Items.Add(tag);
                        AllTagListBox.Items.Add(tag);
                        textBox2.Clear();
                    }
                    catch (Exception ex)
                    {
                        trans.Rollback();
                        MessageBox.Show(this, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
            //}
        }

        private void DeleteTagButton_Click(object sender, EventArgs e)
        {
            Tag tag = DocTagListBox.SelectedItem as Tag;
            if (tag == null)
            {
                return;
            }
            _session.Lock(tag, LockMode.Upgrade);
            using (ITransaction tarns = _session.BeginTransaction())
            {
                try
                {
                    _session.Delete(tag);
                    tarns.Commit();
                    DocTagListBox.Items.Remove(tag);
                    allTagList.Remove(tag);
                    AllTagListBox.Items.Remove(tag);
                }
                catch (Exception ex)
                {
                    tarns.Rollback();
                    MessageBox.Show(this, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }

        }

        private void button1_Click(object sender, EventArgs e)
        {
            DialogResult res = openFileDialog.ShowDialog();
            if (res == DialogResult.OK)
            {
                foreach (string file in openFileDialog.FileNames)
                {
                    Image img = Bitmap.FromFile(file);
                    FileInfo fi = new FileInfo(file);
                    AddPage(img, fi.Name);
                }
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            for (int i = pagesFlowLayoutPanel.Controls.Count - 1; i > -1; i--)
            {
                PageControl p = pagesFlowLayoutPanel.Controls[i] as PageControl;
                if (p.PageSelected)
                {
                    pagesFlowLayoutPanel.Controls.Remove(p);
                    if (p.PageImage == PageControl.pageZoomForm.Image)
                        PageControl.pageZoomForm.Image = null;
                    p.Dispose();
                }
            }
        }

        private void NewDocumentForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            _session.Close();
        }

        private void SaveAndCloseButton_Click(object sender, EventArgs e)
        {
            if (!SaveDocument())
                return;
            DialogResult = DialogResult.OK;
            Close();
        }

        private bool SaveDocument()
        {
            if (string.IsNullOrEmpty(NameTextBox.Text))
            {
                MessageBox.Show(this, "Please enter document name", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }

            if (_doc == null)
                _doc = new Document();

            _doc.Name = NameTextBox.Text;
            _doc.Description = txtDescription.Text;

            using (ITransaction trans = _session.BeginTransaction())
            {
                try
                {
                    foreach (PageControl pc in pagesFlowLayoutPanel.Controls)
                    {
                        Page p = new Page();
                        p.Image = pc.PageImage;
                        p.Name = pc.Name;
                        if (!_doc.Pages.Contains(p))
                        {
                            p.Document = _doc;
                            _doc.Pages.Add(p);
                        }
                        _session.SaveOrUpdate(p);
                    }
                    
                    foreach (Tag tag in DocTagListBox.Items)
                    {
                        tag.Documents.Add(_doc);
                        _doc.Tags.Add(tag);
                        _session.SaveOrUpdate(tag);
                    }

                    _session.SaveOrUpdate(_doc);
                    trans.Commit();
                    NotifyDocumentsUpdated();
                }
                catch (Exception ex)
                {
                    trans.Rollback();
                    MessageBox.Show(ex.Message);
                    return false;
                }
            }
            return true;
        }

        private void NotifyDocumentsUpdated()
        {
            if (DocumentsUpdated != null)
                DocumentsUpdated(this, new EventArgs());
        }

        private void NameTextBox_TextChanged(object sender, EventArgs e)
        {
            this.Text = string.Format("Document - {0}", NameTextBox.Text);
        }

        private void button3_Click(object sender, EventArgs e)
        {
            if (PageControl.pageZoomForm == null)
                PageControl.pageZoomForm = new PageZoom();
            PageControl.pageZoomForm.Owner = this;
            Image img = null;
            foreach (PageControl p in pagesFlowLayoutPanel.Controls)
                if (p.PageSelected)
                {
                    img = p.PageImage;
                    break;
                }
            PageControl.pageZoomForm.Image = img;
            PageControl.pageZoomForm.Show();
        }

        private void SaveAndNewButton_Click(object sender, EventArgs e)
        {
            if (SaveDocument())
                ClearDocument();
        }

        private void ClearDocument()
        {
            NameTextBox.Clear();
            txtDescription.Clear();
            pagesFlowLayoutPanel.Controls.Clear();
            FillDefaultValues();
        }

        private void textBox2_TextChanged(object sender, EventArgs e)
        {
            FilterTags();
        }

        private void FilterTags()
        {
            AllTagListBox.Items.Clear();
            var filteredTags = from filteredTag in allTagList
                               where filteredTag.Name.Contains(textBox2.Text)
                               select filteredTag.Name;
            AllTagListBox.Items.Clear();
            AllTagListBox.Items.AddRange(filteredTags.ToArray<string>());
            UpdateControls();

        }

        private void UpdateControls()
        {
            AddTagButton.Enabled = AllTagListBox.Items.Count == 0 && textBox2.Text != "";
            DeleteTagButton.Enabled = AllTagListBox.SelectedIndex >= 0;
            AddTagIntoDocButton.Enabled = AllTagListBox.SelectedIndex >= 0;
            DropTagFromDocButton.Enabled = DocTagListBox.SelectedIndex >= 0;
            fromDatePicker.Enabled = HasPeriodCheckBox.Checked;
            toDatePicker.Enabled = HasPeriodCheckBox.Checked;
            label4.Enabled = HasPeriodCheckBox.Checked;
            label5.Enabled = HasPeriodCheckBox.Checked;
        }

        private void AllTagListBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            UpdateControls();
        }

        private void AddTagIntoDocButton_Click(object sender, EventArgs e)
        {
            foreach (Tag tag in AllTagListBox.SelectedItems)
            {
                if (!DocTagListBox.Items.Contains(tag))
                    DocTagListBox.Items.Add(tag);
            }
        }

        private void DocTagListBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            UpdateControls();
        }

        private void DropTagFromDocButton_Click(object sender, EventArgs e)
        {
            List<Tag> toRemove = new List<Tag>();            
            foreach (Tag tag in DocTagListBox.SelectedItems)
            {
                toRemove.Add(tag);
            }
            foreach (Tag tag in toRemove)
            {
                DocTagListBox.Items.Remove(tag);
            }
        }

        private void HasPeriodCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            UpdateControls();
        }
    }
}

